package com.raulraja.util.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.util.Arrays;

/**
 * Aspect that Intercepts all methods calls for the different layers and logs the call
 */
@Aspect
public class LayerLogInterceptor {

	private final static Logger logger = Logger.getLogger(LayerLogInterceptor.class);

	/**
	 * Intercepts requests handlers calls
	 */
	@Pointcut("execution(public * com.raulraja.view.demo..*(..))")
	public void requestHandlerMethodPointcut(){
	}


	/**
	 * Intercepts view manager method calls
	 */
	@Pointcut("execution(public * com.raulraja.view.manager.ViewManager+.*(..))")
	public void viewMethodPointcut(){
	}

	/**
	 * Intercepts business services method calls
	 */
	@Pointcut("execution(public * com.raulraja.service.BusinessService+.*(..))")
	public void businessServiceMethodPointcut(){
	}

	/**
	 * Intercepts model manager method calls
	 */
	@Pointcut("execution(public * com.raulraja.model.manager.ModelManager+.*(..))")
	public void modelManagerMethodPointcut(){
	}

	/**
	 * Intercepts persistence adapters method calls
	 */
	@Pointcut("execution(public * com.raulraja.persistence.PersistenceAdapter+.*(..))")
	public void persistenceAdapterMethodPointcut(){
	}

	/**
	 * Provides around advice to view managers method calls by catching any exception an turning them into ExceptionVO objects that can be handled by the view
	 * @param pjp the proceeding join point
	 * @return the object resulting for the operation
	 * @throws Throwable an exception
	 */
	@Around("requestHandlerMethodPointcut() || viewMethodPointcut() || businessServiceMethodPointcut() || modelManagerMethodPointcut() || persistenceAdapterMethodPointcut()")
	public Object applyAroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
		String logPrefix = pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName();
		logger.debug("ENTERING: " + logPrefix +  " with args " + Arrays.toString(pjp.getArgs()));
		Object result = pjp.proceed();
		logger.debug("Returning: " + result);
		logger.debug("EXITING: " + logPrefix);
		return result;
    }

}
